#include "mod_can.h"

#include "platform.h"
#include "can.h"
#include "rtc.h"
#include "utility.h"
#include "log.h"

#include <string.h>
#include <assert.h>

#define CAN_DEBUG_ENABLE 0u

#define CAN_PROTOCOL_MAX 256u

#define CAN_EFF_FLAG 0x80000000U    /*扩展帧的标识*/
#define CAN_RTR_FLAG 0x40000000U    /*远程帧的标识*/
#define CAN_ERR_FLAG 0x20000000U    /*错误帧的标识，用于错误检查*/

#define COST_CONTROL_ADDR     0x8au  /*计费控制单元地址*/
#define CHARGING_CONTROL_ADDR 0xf6u  /*充电控制器地址*/
#define CAN_CMD_MAX 34u              /*can命令数量*/
#define TIMEBASE 250u                /*定时时基*/
#define GUN_NUM 2u                   /*枪数量*/



/*命令状态*/
enum CanCmdState{
   E_CANCMA_NULL = 0,  /*命令不在发送*/
   E_CANCMA_NORMAL ,   /*发送命令正常*/
   E_CANCMA_OVERTIME   /*发送命令超时*/
};


/*正在发送的命令数据*/
struct CanMsgSend {
   uint32_t pgn; /*pgn码*/
   uint8_t  state; /*当前状态*/
   uint32_t timecnt; /*时间间隔*/
   uint32_t overcnt; /*超时次数*/
   uint8_t  buf[100]; /*数据*/
   uint32_t len; /*数据长度*/
};

/*已经接收到的命令数据*/
struct CanMsgRecv {
    struct CanKeepLiveAck keeplive_ack;
    uint8_t keeplive_ack_flag;
    struct CanChargeStartAck start_ack;
    uint8_t start_ack_flag;
    struct CanChargeEndAck stop_ack;
    uint8_t stop_ack_flag;
    struct CanTimeSyncAck time_sync_ack;
    uint8_t time_sync_ack_flag;
    struct CanVerCheckAck ver_check_ack;
    uint8_t ver_check_ack_flag;
    struct CanSetConfigAck set_config_ack;
    uint8_t set_config_ack_flag;
    struct CanSetServerAck set_server_ack;
    uint8_t set_server_ack_flag;
    struct CanSetLockAck set_lock_ack;
    uint8_t set_lock_ack_flag;
    struct CanSetPowerAck set_power_ack;
    uint8_t set_power_ack_flag;
    struct CanReqConfigAck req_config_ack;
    uint8_t req_config_ack_flag;
    struct CanStartChargeFinish start_charge_finish;
    uint8_t start_charge_finish_flag;
    struct CanStopChargeFinish stop_charge_finish;
    uint8_t stop_charge_finish_flag;
    struct CanPgn8192 pgn_8192;
    uint8_t pgn_8192_flag;
    struct CanPgn8704 pgn_8704;
    uint8_t pgn_8704_flag;
    struct CanPgn8960 pgn_8960;
    uint8_t pgn_8960_ack;
    
};

struct CanRecvUnit {
     uint8_t cnt;  /*当前报文序号*/
     uint8_t totalframe;  /*报文总帧数*/
     uint16_t actuallybyte;  /*有效数据段*/
     uint8_t recvmsg[100];  /*接收到的数据*/
	 uint32_t lenrecv;  /*数据长度*/
};

struct CanMgr {
    os_mutex_t mutex;
    struct CanRecvUnit recvunit;  /*接收缓冲区*/
    struct CanMsgRecv recv[GUN_NUM];	 /*接受队列 */
    struct CanMsgSend send[CAN_CMD_MAX*GUN_NUM];	/*发送队列*/
    can_callback callback;
};

struct CanCmdInfo {
   enum CanCmdType pgn;  /*pgn码(命令码)*/
   uint8_t priority;  /*优先级*/
   uint8_t isingleframe;  /*是不是单一帧*/
   uint32_t messagecycle;  /*周期*/
   uint32_t overtime;  /*超时时间*/
};

static const struct CanCmdInfo can_cmd_info[] = {	
    /*命令帧*/
    {CMD_CHARGE_START,      4u,     1u,     250u,   5u},    /*充电启动帧*/
	{CMD_CHARGE_START_ACK,  4u,     1u,     250u,   2u},    /*充电启动帧应答*/
	{CMD_CHARGE_STOP,       4u,     1u,     250u,   5u},    /*充电停止帧*/
    {CMD_CHARGE_STOP_ACK,   4u,     1u,     250u,   2u},    /*充电停止帧应答*/
    {CMD_TIME_SYNC,         6u,     1u,     0u,     0u},    /*对时帧*/
    {CMD_TIME_SYNC_ACK,     6u,     1u,     500u,   2u},    /*对时帧应答*/
    {CMD_VER_CHECK,         6u,     1u,     500u,   5u},    /*版本校验帧*/
    {CMD_VER_CHECK_ACK,     6u,     1u,     500u,   2u},    /*版本校验帧应答*/
    {CMD_CHARGE_PARA,       6u,     1u,     500u,   5u},    /*下发充电参数信息帧*/
    {CMD_CHARGE_PARA_ACK,   6u,     1u,     500u,   2u},    /*下发充电参数信息帧应答*/
    {CMD_SET_SERVER,        4u,     1u,     250u,   5u},    /*充电服务启停控制帧*/
    {CMD_SET_SERVE_ACK,     4u,     1u,     250u,   2u},    /*充电服务启停控制应答帧*/
    {CMD_SET_LOCK,          4u,     1u,     250u,   5u},    /*电子锁控制帧*/
    {CMD_SET_LOCK_ACK,      4u,     1u,     250u,   2u},    /*电子锁控制应答帧*/
    {CMD_SET_POWER,         4u,     1u,     250u,   5u},    /*功率调节控制帧*/
    {CMD_SET_POWER_ACK,     4u,     1u,     250u,   2u},    /*功率调节控制应答帧*/
    {CMD_REQ_CONFIG ,       6u,     1u,     500u,   5u},    /*充电桩配置信息查询帧*/
    {CMD_REQ_CONFIG_ACK,    6u,     0u,     500u,   2u},    /*充电桩配置信息查询应答帧*/
    
    /*状态帧*/
    {CHARGE_START_FINSH,    4u,     0u,     250u,   5u},    /*充电启动完成帧*/
    {CHARGE_START_FINSH_ACK,4u,     1u,     250u,   5u},    /*充电启动完成应答帧*/
    {CHARGE_STOP_FINSH,     4u,     0u,     250u,   5u},    /*充电停止完成帧*/
    {CHARGE_STOP_FINSH_ACK, 4u,     1u,     250u,   5u},    /*充电停止完成应答帧*/
    
    /*直流数据帧*/
    {YC_DC_8192,            6u,     0u,     500u,   0u},    /*遥测帧 充电控制器-计费控制单元0x20*/
    {YC_DC_8448,            6u,     1u,     500u,   0u},    /*遥测帧 计费单元到充电控制器0x21*/
    {YX_DC_8704,            4u,     1u,     500u,   0u},    /*遥信帧 充电控制器到计费单元0x22*/
    {YX_DC_8960,            4u,     1u,     500u,   0u},    /*遥信帧 充电控制器到计费单元0x23*/
    
    /*交流数据帧 暂时不用*/
    {YC_12288,              6u,     0u,     1000u,  0u},    /*遥测帧 充电控制器-计费控制单元*/
    {YC_12544,              6u,     0u,     1000u,  0u},    /*遥测帧 计费单元到充电控制器*/
    {YX_AC_12800,           4u,     1u,     500u,   0u},    /*遥信帧 充电控制器到计费单元*/
    {YX_AC_13056,           4u,     1u,     500u,   0u},    /*遥信帧 计费单元到充电控制器*/
    
    /*心跳帧*/
    {KEEP_LIVE_COST,        6u,     1u,     500u,   0u},    /*计费控制单元心跳帧*/
    {KEEP_LIVE_CONTROL,     6u,     1u,     1000u,  0u},    /*充电控制器心跳帧*/
    
    /*错误帧*/
    {ERROR_COST,            4u,     1u,     250u,   5u},    /*计费控制单元错误状态帧*/
    {ERROR_CONTROL,         4u,     1u,     250u,   5u},    /*充电控制器错误状态帧*/
};

static struct CanMgr Mgr; /*全局指针*/


/*判断是不是单一帧*/
static int32_t is_single_frame(uint8_t pf) { 
    int32_t i;
    uint8_t tmppf = 0u;
    int32_t ret = -1;

    for(i = 0; i<(int32_t)(sizeof(can_cmd_info)/sizeof(struct CanCmdInfo)); i++) {
        tmppf = (uint8_t)((uint16_t)can_cmd_info[i].pgn >> 8);
        if(tmppf == pf) {
            ret = (int32_t)can_cmd_info[i].isingleframe;
            break;
		}
	}
    return ret;
}

static uint32_t get_pgn(uint8_t pf) {
    int32_t i;
    uint8_t tmppf = 0u;
    uint32_t pgn = 0u;

    for(i = 0; i < (int32_t)(sizeof(can_cmd_info)/sizeof(struct CanCmdInfo)); i++) {
        tmppf = (uint8_t)((uint16_t)can_cmd_info[i].pgn >> 8);
        if(tmppf == pf) {
            pgn = (uint32_t)can_cmd_info[i].pgn;
            break;
        }
    }
    return pgn;
}

/*拿取优先级*/
static int32_t get_priority(uint32_t pgn) {
    int32_t i;
    int32_t ret = 0;
    for(i = 0; i<(int32_t)(sizeof(can_cmd_info)/sizeof(struct CanCmdInfo)); i++) {
        if((uint32_t)can_cmd_info[i].pgn == pgn) {
            ret = (int32_t)can_cmd_info[i].priority;
            break;
        }
    }
    return ret;
}

/*拿取超时时间*/
static uint32_t get_over_time(uint32_t pgn) {
    int32_t i;
    uint32_t time = 0u;
    for(i = 0; i<(int32_t)(sizeof(can_cmd_info)/sizeof(struct CanCmdInfo)); i++) {
        if((uint32_t)can_cmd_info[i].pgn == pgn) {
            time = (uint32_t)can_cmd_info[i].overtime;
            break;
        }
    }
    return time;
}

/*拿取周期*/
static uint32_t gettimecycle(uint32_t pgn) {
    int32_t i;
    uint32_t cycle = 0u;
    for(i = 0; i < (int32_t)(sizeof(can_cmd_info)/sizeof(struct CanCmdInfo)); i++) {
        if((uint32_t)can_cmd_info[i].pgn == pgn) {
            cycle = can_cmd_info[i].messagecycle;
            break;
        }
    }
    return cycle;	
}

static uint32_t get_pgn_pos(uint32_t pgn,uint32_t gunnum) {
    int32_t i;
    uint32_t pos = CAN_CMD_MAX * GUN_NUM;
    
    for(i = 0; i < (int32_t)(sizeof(can_cmd_info)/sizeof(struct CanCmdInfo)); i++) {
        if((uint32_t)can_cmd_info[i].pgn == pgn) {
            pos = (uint32_t)(((uint32_t)i * (GUN_NUM)) + (gunnum - 1u));
            break;
        }
    }
    return pos;	
}

static void add_cansend(struct CanMgr *msg,uint32_t gunnum,uint32_t pgn, const uint8_t *buf,int32_t len)
{
    uint32_t pos = get_pgn_pos(pgn,gunnum);

	os_mutex_lock(&msg->mutex) ;/*加锁*/
	
	msg->send[pos].pgn = pgn; 
    msg->send[pos].timecnt = 0u;/*时间间隔为0*/
    msg->send[pos].overcnt = 0u;/*超时次数为0*/
    memcpy(msg->send[pos].buf, buf, (uint32_t)len);/*数据*/
    msg->send[pos].len = (uint32_t)len;/*数据长度*/
	msg->send[pos].state = (uint8_t)E_CANCMA_NORMAL;/*当前状态正常*/
    
	os_mutex_unlock(&msg->mutex); /*解锁*/
}

static void can_module_send(uint32_t gunnum,uint32_t pgn,const uint8_t *buf,int32_t len){
    if(gunnum <= GUN_NUM) {
		add_cansend(&Mgr, gunnum, pgn, buf, len);
	}	
}

/*启动充电帧*/
void can_start_charging(uint32_t gunnum,uint32_t control) {
	int32_t pos = 0;
	uint8_t buf[CAN_PROTOCOL_MAX] = {0u};
	
	pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
	
	pos = ut_setbyte(buf,pos,(uint8_t)control);
	
    can_module_send(gunnum, (uint32_t)CMD_CHARGE_START, buf, pos);
}

/*停止充电帧*/
void can_stop_charging(uint32_t gunnum,uint32_t reason) {
	int32_t pos = 0;
	uint8_t buf[CAN_PROTOCOL_MAX] = {0u};
	
	pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
	
	pos = ut_setbyte(buf,pos,(uint8_t)reason);
	
    can_module_send(gunnum,(uint32_t)CMD_CHARGE_STOP,buf,pos);
}

/*下发对时帧*/
void can_time_sync(uint32_t gunnum, uint16_t year, uint8_t mon, uint8_t date, uint8_t hour, uint8_t min, uint16_t sec) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
        
    pos = ut_setshort(buf,pos, (uint16_t)(sec*1000u));
    pos = ut_setbyte(buf,pos,min);
    pos = ut_setbyte(buf,pos,hour);
    pos = ut_setbyte(buf,pos,date);
    pos = ut_setbyte(buf,pos,mon+1u);
    pos = ut_setbyte(buf,pos,(uint8_t)((year+1900u)-2000u));
     
    can_module_send(gunnum,(uint32_t)CMD_TIME_SYNC,buf,pos);
}

/*版本校验帧*/
void can_ver_check(uint32_t gunnum,uint32_t ver) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
    pos = ut_setshort(buf,pos,(uint16_t)ver);

    can_module_send(gunnum,(uint32_t)CMD_VER_CHECK,buf,pos);
}

/*下发充电参数信息帧*/
void can_set_charging_para(uint32_t gunnum,const uint8_t *data,int32_t len) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf, pos, (uint8_t)gunnum);
    pos = ut_setnbyte(buf, pos, data, len);

    can_module_send(gunnum, (uint32_t)CMD_CHARGE_PARA, buf, pos);
}

/*充电服务启停帧*/
void can_set_charging_service(uint32_t gunnum,uint32_t cmd) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf, pos, (uint8_t)gunnum);
    pos = ut_setbyte(buf, pos, (uint8_t)cmd);

    can_module_send(gunnum,(uint32_t)CMD_SET_SERVER, buf, pos);
}

/*电子锁控制帧*/
void can_set_lock_control(uint32_t gunnum,uint32_t no,uint32_t cmd) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
    pos = ut_setbyte(buf,pos,(uint8_t)no);
    pos = ut_setbyte(buf,pos,(uint8_t)cmd);

    can_module_send(gunnum,(uint32_t)CMD_SET_LOCK,buf,pos);
}

/*功率调节帧*/
void can_set_power(uint32_t gunnum,uint32_t type,uint32_t value) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
    pos = ut_setbyte(buf,pos,(uint8_t)type);
    pos = ut_setshort(buf,pos,(uint16_t)value);

    can_module_send(gunnum,(uint32_t)CMD_SET_POWER,buf,pos);
}

/*充电桩配置参数查询帧*/
void can_req_dev_config(uint32_t gunnum) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf,pos,(uint8_t)gunnum);

    can_module_send(gunnum,(uint32_t)CMD_REQ_CONFIG,buf,pos);
}

/*充电启动完成帧应答*/
void can_start_charging_finish_ack(uint32_t gunnum,uint32_t control,uint32_t flag) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
    pos = ut_setbyte(buf,pos,(uint8_t)control);
    pos = ut_setbyte(buf,pos,(uint8_t)flag);

    can_module_send(gunnum,(uint32_t)CHARGE_START_FINSH_ACK,buf,pos);
}

/*充电停止完成应答*/
void can_stop_charging_finish_ack(uint32_t gunnum,uint32_t flag) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
    pos = ut_setbyte(buf,pos,(uint8_t)flag);

    can_module_send(gunnum,(uint32_t)CHARGE_STOP_FINSH_ACK,buf,pos);
}

/*8448遥测帧*/
void can_send_8448(uint32_t gunnum,uint32_t totalkwh,uint32_t totaltime) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
    pos = ut_setshort(buf,pos,(uint16_t)totalkwh);
    pos = ut_setshort(buf,pos,(uint16_t)totaltime);

    can_module_send(gunnum,(uint32_t)YC_DC_8448,buf,pos);
}

/*12544遥测帧*/
void can_send_12544(void) {
	
}

/*心跳帧*/
void can_send_keeplive(uint32_t gunnum,uint8_t state) {
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};

    pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
    pos = ut_setbyte(buf,pos,(uint8_t)0u);
    pos = ut_setbyte(buf,pos,(uint8_t)state);
    can_module_send(gunnum,(uint32_t)KEEP_LIVE_COST,buf,pos);
}

void can_send_error(uint32_t gunnum, enum CAN_ERR code) {
    uint16_t err = 0u;
    int32_t pos = 0;
    uint8_t buf[CAN_PROTOCOL_MAX] = {0u};
    
    err |= (uint16_t)code;   
    
    pos = ut_setbyte(buf,pos,(uint8_t)gunnum);
    pos = ut_setbyte(buf,pos,(uint8_t)(err & 0x00ffu));
    pos = ut_setbyte(buf,pos,(uint8_t)((err >> 8u) & 0x00ffu));
    can_module_send(gunnum,(uint32_t)ERROR_COST,buf,pos);
}
#if 0
static uint8_t get_total_frame(uint32_t msgsize)
{
    uint8_t totalframe = 0u;
    uint32_t sizetotal = msgsize +5u;
    
    if( 0u == (sizetotal%7u)) {
       totalframe = (uint8_t)(sizetotal/7u);
    }
    else {
       totalframe = (uint8_t)((sizetotal/7u)+1u);
    }
    return totalframe;
}
#endif
static uint16_t cal_crc(const uint8_t *buf,uint32_t len)
{
     uint16_t value = 0u;
	 int32_t i;
     for(i = 0; i < (int32_t)len; i++) {
         value = value + *(buf+i);
     }
     return value;
}

/*处理多帧*/
static int32_t deal_complex_frame(struct CanRecvUnit *unit, const uint8_t *buf)
{
    uint16_t l,h;
    uint8_t num = *(buf+0) ;/*报文序号*/
    if ((uint8_t)(unit->cnt + 1) != num) {
        memset(unit,0,sizeof(struct CanRecvUnit));
        return -1;
    }
	unit->cnt = num;
	if(unit->cnt == (uint8_t)1) {/*说明是多帧数据的第一帧*/
	
	   unit->totalframe = *(buf+1u);/*报文总帧数*/
	   
	   l = (uint16_t)(*(buf+2u));
	   h = (uint16_t)((uint16_t)(*(buf+3u)) << 8u);
	   unit->actuallybyte = h|l; /*有效数据段*/
	   
	   /*printf("totalframe = %d actuallybyte = %d\r\n",unit->totalframe,unit->actuallybyte );*/
	}
    
    if (unit->lenrecv + 7u > sizeof(unit->recvmsg)){
        printf("deal_complex_frame len:%d err\r\n", unit->lenrecv);
        memset(unit,0,sizeof(struct CanRecvUnit));
        return -1;
    }
    
    memcpy(unit->recvmsg+unit->lenrecv, buf+1u, 7u);	   /*第一帧是序号 有效数据为7个*/
    unit->lenrecv = unit->lenrecv + 7u;  /*数据长度*/
    #if 0
    printf("len_recv:%d\r\n", unit->lenrecv);
    for(uint32_t i=0;i< unit->lenrecv;i++){
        printf("%x ", unit->recvmsg[i]);
    }
    printf("\r\n");
	#endif
	return 0;	
}
#if 0
void made_alarm_code(int recv_pgn, uint8_t *data, int len){
    char str[10] = {0};
    /*data_getstr("alarmcode", str, sizeof(str));*/
    if (recv_pgn == 8704){
        struct CanPgn8704 *pgn = (struct CanPgn8704 *)data;
        if (strncmp(str, "3004", 4) == 0){ /*系统风扇故障*/
            pgn->dev_fan = 1;
        }else if (strncmp(str, "3005", 4) == 0){ /*模块风扇故障*/
            pgn->mod_fan_fail = 1;
        }else if (strncmp(str, "3008", 4) == 0){ /*模块通信故障*/
            pgn->mod_comm_fail = 1;
        }else if (strncmp(str, "300A", 4) == 0){ /*电源模块故障*/
            pgn->mod_fail = 1;
        }else if (strncmp(str, "300B", 4) == 0){ /*电源模块过温告警*/
            pgn->mod_temp_over = 1;
        }else if (strncmp(str, "3016", 4) == 0){ /*充电桩过温报警*/
            pgn->dev_over_temp = 1;
        }else if (strncmp(str, "3017", 4) == 0){ /*充电接口过温保护*/
            pgn->gun_over_temp = 1;
        }else if (strncmp(str, "3018", 4) == 0){ /*充电接口电子锁故障*/
            pgn->gun_elec_lock = 1;
        }else if (strncmp(str, "3010", 4) == 0){ /*直流接触器故障*/
            pgn->dc_bus_contact = 1;
        }else if (strncmp(str, "3011", 4) == 0){ /*直流熔断器故障*/
            pgn->dc_bus_fuse = 1;
        }else if (strncmp(str, "301B", 4) == 0){ /*充电连接故障*/
            pgn->charging_vcg = 1;
        }else if (strncmp(str, "301D", 4) == 0){ /*充电桩其他故障*/
            pgn->otherfail = 0x0800;
        }else if (strncmp(str, "4009", 4) == 0){ /*输入缺相报警*/
            pgn->mod_ac_lost_phase = 1;
        }else if (strncmp(str, "400C", 4) == 0){ /*交流防雷报警*/
            pgn->arrester = 1;
        }  

    }else if (recv_pgn == 512){
        struct CanChargeStartAck *pgn = (struct CanChargeStartAck *)data;
        if (strncmp(str, "5000", 4) == 0){ /*BMS通讯异常*/
            pgn->failreason = 0x12;
            pgn->flag = 1;
        }else if (strncmp(str, "501A", 4) == 0){ /*电池反接*/
            pgn->failreason = 0x11;
            pgn->flag = 1;
        }
    }else if (recv_pgn == 8960){
        struct CanPgn8960 *pgn = (struct CanPgn8960 *)data;
        if (strncmp(str, "300F", 4) == 0){ /*输出接触器粘连*/
            pgn->dc_contact_adhesion = 1;
        }else if (strncmp(str, "3013", 4) == 0){ /*辅助电源故障*/
            pgn->aux_power_fail = 1;
        }else if (strncmp(str, "3015", 4) == 0){ /*泄放回路故障*/
            pgn->release_fail = 1;
        }else if (strncmp(str, "3014", 4) == 0){ /*枪1或枪2绝缘监测故障*/
            pgn->insulate_check_fail = 1;
        }

    }else if (recv_pgn == 4352){
        struct CanStartChargeFinish *pgn = (struct CanStartChargeFinish*)data;
        if (strncmp(str, "4006", 4) == 0){ /*继电器外侧电压大于10v*/
            pgn->failreason = 0x1d;
            pgn->flag = 1;
        }else if (strncmp(str, "5001", 4) == 0){ /*BCP充电参数配置报文超时*/
            pgn->failreason = 0x24;
            pgn->flag = 1;
        }else if (strncmp(str, "5002", 4) == 0){ /*BRO充电准备就绪报文超时*/
            pgn->failreason = 0x26;
            pgn->flag = 1;
        }        
        
    }else if (recv_pgn == 4864){ /*充电停止完成帧*/
        struct CanStopChargeFinish *pgn = (struct CanStopChargeFinish *)data;
        if (strncmp(str, "4000", 4) == 0){ /*交流输入故障*/
            pgn->stopreason = 0x0f;
        }else if (strncmp(str, "4001", 4) == 0){ /*直流输出电压过压*/
            pgn->stopreason = 0x1b;
        }else if (strncmp(str, "4002", 4) == 0){ /*直流输出电流过流*/
            pgn->stopreason = 0x1d;
        }else if (strncmp(str, "4003", 4) == 0){ /*直流输出电压欠压*/
            pgn->stopreason = 0x1c;
        }else if (strncmp(str, "4004", 4) == 0){ /*直流输出短路*/
            pgn->stopreason = 0x1e;
        }else if (strncmp(str, "5003", 4) == 0){ /*BCS电池充电状态报文超时*/
            pgn->stopreason = 0x20;
        }else if (strncmp(str, "5004", 4) == 0){ /*BCL电池充电需求报文超时*/
            pgn->stopreason = 0x1f;
        }else if (strncmp(str, "5005", 4) == 0){ /*BST中止充电报文超时*/
            pgn->recvbmsstopchaover = 1;
        }else if (strncmp(str, "5006", 4) == 0){ /*BSD充电统计数据报文超时*/
            pgn->recvbmschacalover = 1;
        }else if (strncmp(str, "5007", 4) == 0){ /*BSM动力蓄电池状态报文超时*/
            pgn->recvbattchastateover = 1;
        }else if (strncmp(str, "500A", 4) == 0){ /*BRM车辆辨识报文超时*/
            pgn->recvbmsover = 1;
        }else if (strncmp(str, "5012", 4) == 0){ /*单体动力蓄电池电压过高*/
            pgn->stopreason = 0x22;
        }else if (strncmp(str, "5013", 4) == 0){ /*单体动力蓄电池电压过低*/
            pgn->stopreason = 0x23;
        }else if (strncmp(str, "5014", 4) == 0){ /*整车动力蓄电池荷电状态SOC过高*/
            pgn->stopreason = 0x24;
        }else if (strncmp(str, "5015", 4) == 0){ /*整车动力蓄电池荷电状态SOC过低*/
            pgn->stopreason = 0x25;
        }else if (strncmp(str, "5016", 4) == 0){ /*动力蓄电池充电过流*/
            pgn->stopreason = 0x26;
        }else if (strncmp(str, "5017", 4) == 0){ /*动力蓄电池温度过高*/
            pgn->stopreason = 0x27;
        }else if (strncmp(str, "5018", 4) == 0){ /*动力蓄电池绝缘故障*/
            pgn->stopreason = 0x28;
        }else if (strncmp(str, "5019", 4) == 0){ /*动力蓄电池连接器故障*/
            pgn->stopreason = 0x29;
        }
    }
}
#endif
static void recv_data_deal(const struct CanMgr *mgr, struct CanMsgRecv *msg, uint32_t pgn,  uint8_t *data, uint32_t len){
    
    /*made_alarm_code(pgn, data, len); 模拟故障发生*/
    switch(pgn){
        case KEEP_LIVE_CONTROL:
            memcpy(&msg->keeplive_ack, data, sizeof(msg->keeplive_ack));
            msg->keeplive_ack_flag = 1;
        break;
        case CMD_CHARGE_START_ACK:
            memcpy(&msg->start_ack, data, sizeof(msg->start_ack));
            msg->start_ack_flag = 1;
        break;
        case CMD_CHARGE_STOP_ACK:
            memcpy(&msg->stop_ack, data, sizeof(msg->stop_ack));
            msg->stop_ack_flag = 1;
        break;
        case CMD_TIME_SYNC_ACK:
            memcpy(&msg->time_sync_ack, data, sizeof(msg->time_sync_ack));
            msg->time_sync_ack_flag = 1;
        break;
        case CMD_VER_CHECK_ACK:
            memcpy(&msg->ver_check_ack, data, sizeof(msg->ver_check_ack));
            msg->ver_check_ack_flag = 1;
        break;
        case CMD_CHARGE_PARA_ACK:
            memcpy(&msg->set_config_ack, data, sizeof(msg->set_config_ack));
            msg->set_config_ack_flag = 1;
        break;
        case CMD_SET_SERVE_ACK:
            memcpy(&msg->set_server_ack, data, sizeof(msg->set_server_ack));
            msg->set_server_ack_flag = 1;
        break;
        case CMD_SET_LOCK_ACK:
            memcpy(&msg->set_lock_ack, data, sizeof(msg->set_lock_ack));
            msg->set_lock_ack_flag = 1;
        break;
        case CMD_SET_POWER_ACK:
            memcpy(&msg->set_power_ack, data, sizeof(msg->set_power_ack));
            msg->set_power_ack_flag = 1;
        break;
        case CMD_REQ_CONFIG_ACK:
            memcpy(&msg->set_config_ack, data, sizeof(msg->set_config_ack));
            msg->set_config_ack_flag = 1;
        break;
        case CHARGE_START_FINSH:
            memcpy(&msg->start_charge_finish, data, sizeof(msg->start_charge_finish));
            msg->start_charge_finish_flag = 1;
        break;
        case CHARGE_STOP_FINSH:
            memcpy(&msg->stop_charge_finish, data, sizeof(msg->stop_charge_finish));
            msg->stop_charge_finish_flag = 1;
        break;
        case YC_DC_8192:
            memcpy(&msg->pgn_8192, data, sizeof(msg->pgn_8192));
            msg->pgn_8192_flag = 1;
        break;
        case YX_DC_8704:
            memcpy(&msg->pgn_8704, data, sizeof(msg->pgn_8704));
            msg->pgn_8704_flag = 1;
        break;
        case YX_DC_8960:
            memcpy(&msg->pgn_8960, data, sizeof(msg->pgn_8960));
            msg->pgn_8960_ack = 1;
        break;
        default:
            log(LOG_WARNING, "recv_data_deal cant deal cmd:%x ack\r\n", pgn);
        break;
    }

    if (mgr->callback != NULL){
        mgr->callback(pgn, data, len);
    }

    #if CAN_DEBUG_ENABLE /*调试打印开关*/
    //if (msg->buf[0] == 0x02){
        printf("%s,>>>>>pgn = %d len = %d buf: ",msg->time, pgn, len);

        uint32_t i;
        for(i = 0;i< msg->len;i++)
        {
        	printf("%02x ",*(msg->buf+i));
        }
        printf("\r\n");
        /*printpgn(pgn, msg->buf, msg->len);*/
//    }
    #endif  
}

static void can_recv_deal(struct CanMgr *mgr, struct CanMsgRx *msg,struct CanRecvUnit *unit) {  
    uint8_t sarecv = (uint8_t)(msg->id & (uint8_t)0xff);/*充电控制器地址*/
    uint8_t psrecv = (uint8_t)((msg->id >> 8) & (uint8_t)0xff);/*计费控制单元地址*/   
    uint8_t pfrecv = (uint8_t)((msg->id >> 16) & (uint8_t)0xff);/*PDU码*/
    uint32_t pgn =  get_pgn(pfrecv);
    /*uint32_t precv = (frame->can_id<<3)>>29; 优先权*/

    if((sarecv != CHARGING_CONTROL_ADDR) || (psrecv != COST_CONTROL_ADDR)) {  
       printf("src or dsc addr err\r\n"); 
    }else{
        int32_t issig = is_single_frame(pfrecv);
        
        if(issig == 1) { /*如果是单一帧*/
            //printf("is=1\r\n");
            uint32_t gunnum = *(msg->data);/*通常第一个字节为枪号 跟协议有点绑定了*/        
            recv_data_deal(mgr, &mgr->recv[gunnum-1], pgn,  msg->data, (uint32_t)msg->len);
        
        } else if(issig == 0){ 
            
            if(deal_complex_frame(unit,msg->data) != 0)/*处理多帧*/{
                
                return;
            }
            
            if(unit->cnt == unit->totalframe) {/*报文序号等于报文总帧数*/
                uint8_t *p = unit->recvmsg;
                uint16_t len = unit->actuallybyte;
                uint16_t crch = (uint16_t)((uint16_t)(*(p+len+3u+1u)) << 8u);						
                uint16_t crcl = (uint16_t)(*(p+len+3u+0u));
                uint16_t crc = crch|crcl;
                uint16_t crccal = (uint16_t)cal_crc(p,(uint32_t)((uint32_t)len+3u));/*算出crc	*/
                
                if(crccal == crc) { /*crc正确*/                                    
                   uint32_t gunnum = *(p+3);/*通常第一个字节为枪号 跟协议有点绑定了*/
                   recv_data_deal(mgr, &mgr->recv[gunnum-1], pgn, (p+3), (uint32_t)len);
                   
                }else {/*crc验证错误*/
                    log(LOG_ERR, "can recv crc error len:%d pdu:%x crccal:%x crcrecv:%x\r\n", len, (int32_t)pfrecv, crccal, crc);
                    for(uint32_t i=0;i<len;i++){
                        printf("%02x ",*(p+i));
                    }  
                    printf("\r\n");
                }
                memset(unit,0,sizeof(struct CanRecvUnit));
            }
            
        }else{
           //printf("pf:%x not exist\r\n", (int32_t)pfrecv); 
        }
    }
}

void can_print(struct CanMsgRx *msg){
    printf("can recv: id:%x len:%d data: ", msg->id, msg->len);
    for(uint32_t i = 0; i< msg->len; i++){
        printf("%02x", msg->data[i]);
    }
    printf("\r\n");
}

static void can_recv(struct CanMgr *mgr){
    struct CanMsgRx recv_msg;
    if (can1_rec_msg(&recv_msg)){
        //can_print(&recv_msg);
        can_recv_deal(mgr, &recv_msg, &mgr->recvunit);/*解析*/
    }
}

static void send_can_frame(uint32_t pgn,const uint8_t *buf,uint32_t len)
{
    uint8_t buf_tmp[8]={0};
    uint32_t p = (uint32_t)get_priority(pgn);
    /*uint32_t r = 0u;*/
    /*uint32_t dp = 0u;*/
    uint32_t pf = (uint32_t)(pgn>>8);/*pf值取PGN的第二个字节*/
    uint32_t ps = CHARGING_CONTROL_ADDR;
    uint32_t sa = COST_CONTROL_ADDR;
    uint32_t canid = CAN_EFF_FLAG;/*拓展帧*/
    
    canid = canid |  sa;
    canid = canid | (ps << 8);
    canid = canid | (pf << 16);
    /*canid = canid | (dp << 24);*/
    /*canid = canid | (r << 25);*/
    canid = canid | (p << 26);
    #if CAN_DEBUG_ENABLE /*调试打印开关 */
   // if (buf[0] == 0x02){
    	printf("<<<<<pgn = %d len = %d buf: ",pgn,len);
        uint32_t j;
        for(j = 0;j< len ;j++)
    	{
    	   printf("%02x ",*(buf+j));
    	}			
        printf("\r\n");	
  //  }
	#endif	
    if (len>8){
        log(LOG_ERR, "send_can_frame len err\r\n");
        return;
    }
    memset(buf_tmp, 0, sizeof(buf_tmp));
    memcpy(buf_tmp, buf, len);
    can1_send_msg(canid,buf_tmp,8);
}

static void can_send(struct CanMgr *msg) {	
   int32_t i;
   uint32_t overtimetmp;
    
   os_mutex_lock(&msg->mutex) ;/*加锁*/
    
    for(i = 0; i < (int32_t)(CAN_CMD_MAX*GUN_NUM); i++) {	
        struct CanMsgSend *msgsend =  &msg->send[i];
          
        if(msgsend->state == (uint8_t)E_CANCMA_NORMAL) {/*只有正常状态下ptimecnt 才++*/
           msgsend->timecnt += TIMEBASE;/*时间间隔增加*/
        }
        if((msgsend->timecnt >= gettimecycle(msgsend->pgn)) && (msgsend->state == (uint8_t)E_CANCMA_NORMAL)) {	  
            if(gettimecycle(msgsend->pgn) == (uint32_t)0) { /*发送周期为 0*/
               msgsend->state =  (uint8_t)E_CANCMA_OVERTIME;/*置为超时状态 表示发送一次就不发送看 */
            }		
            msgsend->timecnt  = 0u;/*时间间隔增加*/
            if(is_single_frame((uint8_t)(msgsend->pgn >> 8)))  { /*单帧数据*/	
              send_can_frame(msgsend->pgn,msgsend->buf,msgsend->len);
            }
            else {/*多帧数据*/  
              printf("many frame is not deal pgn:%d\r\n", (int32_t)msgsend->pgn);
            }
           
            overtimetmp = (uint32_t)((uint32_t)get_over_time(msgsend->pgn) *1000u);/*超时时间ms*/	
            
            if((uint32_t)0 != overtimetmp) {/*超时周期不为0 才++*/
                msgsend->overcnt += TIMEBASE;
            }
            
            if(	(msgsend->overcnt > overtimetmp) && (overtimetmp != (uint32_t)0) ) {/*发送超时*/
                msgsend->state =  (uint8_t)E_CANCMA_OVERTIME;/*置为超时状态*/		  
                msgsend->overcnt = 0u;/*超时计数为0*/
            }           
        }			
    }
    os_mutex_unlock(&msg->mutex); /*解锁*/
}

static int32_t can_init(struct CanMgr *msg, can_callback callback) {
    memset(msg,0,sizeof(struct CanMgr));
    msg->mutex = os_mutex_create();
    msg->callback = callback;
    return can1_init();
}

static int32_t get_canrecv(struct CanMgr *mgr,uint32_t gunnum,uint32_t pgn,uint8_t *buf) {
    int32_t len = 0;
    struct CanMsgRecv *msg = &mgr->recv[gunnum-1];
       
    switch(pgn){
        case KEEP_LIVE_CONTROL:
            if (msg->keeplive_ack_flag){
                memcpy(buf, &msg->keeplive_ack, sizeof(msg->keeplive_ack));
                len = sizeof(msg->keeplive_ack);
                msg->keeplive_ack_flag = 0;
            }
        break;
        case CMD_CHARGE_START_ACK:
            if (msg->start_ack_flag){
                memcpy(buf, &msg->start_ack, sizeof(msg->start_ack));
                len = sizeof(msg->start_ack);
                msg->start_ack_flag = 0;
            }
        break;
        case CMD_CHARGE_STOP_ACK:
            if(msg->stop_ack_flag){
                memcpy(buf, &msg->stop_ack, sizeof(msg->stop_ack));
                len = sizeof(msg->stop_ack);
                msg->stop_ack_flag = 0;            
            }
        break;
        case CMD_TIME_SYNC_ACK:
            if (msg->time_sync_ack_flag){
                memcpy(buf, &msg->time_sync_ack, sizeof(msg->time_sync_ack));
                len = sizeof(msg->time_sync_ack);
                msg->time_sync_ack_flag = 0;            
            }
        break;
        case CMD_VER_CHECK_ACK:
            if (msg->ver_check_ack_flag){
                memcpy(buf, &msg->ver_check_ack, sizeof(msg->ver_check_ack));
                len = sizeof(msg->ver_check_ack);
                msg->ver_check_ack_flag = 0;            
            }
        break;
        case CMD_CHARGE_PARA_ACK:
            if (msg->set_config_ack_flag){
                memcpy(buf, &msg->set_config_ack, sizeof(msg->set_config_ack));
                len = sizeof(msg->set_config_ack);
                msg->set_config_ack_flag = 0;            
            }
        break;
        case CMD_SET_SERVE_ACK:
            if (msg->set_server_ack_flag){
                memcpy(buf, &msg->set_server_ack, sizeof(msg->set_server_ack));
                len = sizeof(msg->set_server_ack);
                msg->set_server_ack_flag = 0;           
            }
        break;
        case CMD_SET_LOCK_ACK:
            if (msg->set_lock_ack_flag){
                memcpy(buf, &msg->set_lock_ack, sizeof(msg->set_lock_ack));
                len = sizeof(msg->set_lock_ack);
                msg->set_lock_ack_flag = 0;
            }
        break;
        case CMD_SET_POWER_ACK:
            if (msg->set_power_ack_flag){
                memcpy(buf, &msg->set_power_ack, sizeof(msg->set_power_ack));
                len = sizeof(msg->set_power_ack);
                msg->set_power_ack_flag = 0;
            }
        break;
        case CMD_REQ_CONFIG_ACK:
            if (msg->set_config_ack_flag){
                memcpy(buf, &msg->set_config_ack, sizeof(msg->set_config_ack));
                len = sizeof(msg->set_config_ack);
                msg->set_config_ack_flag = 0;
            }
        break;
        case CHARGE_START_FINSH:
            if (msg->start_charge_finish_flag){
                memcpy(buf, &msg->start_charge_finish, sizeof(msg->start_charge_finish));
                len = sizeof(msg->start_charge_finish);
                msg->start_charge_finish_flag = 0;
            }
        break;
        case CHARGE_STOP_FINSH:
            if (msg->stop_charge_finish_flag){
                memcpy(buf, &msg->stop_charge_finish, sizeof(msg->stop_charge_finish));
                len = sizeof(msg->stop_charge_finish);
                msg->stop_charge_finish_flag = 0;           
            }
        break;
        case YC_DC_8192:
            if (msg->pgn_8192_flag){
                memcpy(buf, &msg->pgn_8192, sizeof(msg->pgn_8192));
                len = sizeof(msg->pgn_8192);
                msg->pgn_8192_flag = 0;
            }
        break;
        case YX_DC_8704:
            if (msg->pgn_8704_flag){
                memcpy(buf, &msg->pgn_8704, sizeof(msg->pgn_8704));
                len = sizeof(msg->pgn_8704);
                msg->pgn_8704_flag = 0;
            }
        break;
        case YX_DC_8960:
            if (msg->pgn_8960_ack){
                memcpy(buf, &msg->pgn_8960, sizeof(msg->pgn_8960));
                len = sizeof(msg->pgn_8960);
                msg->pgn_8960_ack = 0;
            }
        break;
        default:
            log(LOG_WARNING, "recv_data_deal cant deal cmd ack\r\n");
        break;
    }

    return len;
}

static void clear_canrecv(struct CanMgr *mgr,uint32_t gunnum,uint32_t pgn){
    struct CanMsgRecv *msg = &mgr->recv[gunnum-1];
    
    switch(pgn){
        case KEEP_LIVE_CONTROL:
            msg->keeplive_ack_flag = 0;
        break;
        case CMD_CHARGE_START_ACK:
            msg->start_ack_flag = 0;
        break;
        case CMD_CHARGE_STOP_ACK:
            msg->stop_ack_flag = 0;  
        break;
        case CMD_TIME_SYNC_ACK:
            msg->time_sync_ack_flag = 0; 
        break;
        case CMD_VER_CHECK_ACK:
            msg->ver_check_ack_flag = 0; 
        break;
        case CMD_CHARGE_PARA_ACK:
            msg->set_config_ack_flag = 0;            
        break;
        case CMD_SET_SERVE_ACK:
            msg->set_server_ack_flag = 0;           
        break;
        case CMD_SET_LOCK_ACK:
            msg->set_lock_ack_flag = 0;
        break;
        case CMD_SET_POWER_ACK:
            msg->set_power_ack_flag = 0;
        break;
        case CMD_REQ_CONFIG_ACK:
            msg->set_config_ack_flag = 0;
        break;
        case CHARGE_START_FINSH:
            msg->start_charge_finish_flag = 0;
        break;
        case CHARGE_STOP_FINSH:
            msg->stop_charge_finish_flag = 0;           
        break;
        case YC_DC_8192:
            msg->pgn_8192_flag = 0;
        break;
        case YX_DC_8704:
            msg->pgn_8704_flag = 0;
        break;
        case YX_DC_8960:
            msg->pgn_8960_ack = 0;
        break;
        default:
            log(LOG_WARNING, "recv_data_deal cant deal cmd ack\r\n");
        break;
    }
}

static void can_send_task(void *arg)    
{
    arg = arg; /*lint 715*/
    
    //can_send_keeplive(0, E_KEEPLIVE_NORMAL);
    //can_send_keeplive(1, E_KEEPLIVE_NORMAL);
    
    /*lint -e(716) */
    while(1)
    {
	   os_msleep(TIMEBASE) ;
       can_send(&Mgr);/*发送操作 */     
	}
}

static void can_recv_task(void *arg)
{	 
    arg = arg;
    
    os_msleep(3000u);
    
    /*lint -e(716) */
    while(1)
    {		
        can_recv(&Mgr);
        os_msleep(10u);
    }
}

int32_t can_module_init(can_callback callback){
    int32_t ret;
    os_pthread_t task1;
    os_pthread_t task2;  
    
    memset(&Mgr, 0, sizeof(Mgr));
    
    ret = can_init(&Mgr, callback);
    if (ret == -1){
        printf("can_init failed!\n");
        
        /*lint -e(904) */
        return -1;
    }

    /*can发送任务*/
    ret = os_pthread_create("can_send", &task1, can_send_task, NULL, OS_TASK_PRIO_ABOVE_NOMAL, OS_STACK_SIZE_LARGE);
    if (ret == -1)
    {
        printf("create tidp1 failed!\n");
        
        /*lint -e(904) */
        return -1;
    }  
    
    /*can接收任务*/
	ret = os_pthread_create("can_recv", &task2, can_recv_task, NULL, OS_TASK_PRIO_ABOVE_NOMAL, OS_STACK_SIZE_LARGE);
    if (ret == -1)
    {
        printf("create tidp2 failed!\n");
        
        /*lint -e(904) */
        return -1;
    }     
    
    return 0;
}

int32_t can_module_recv(uint32_t gunnum,uint32_t pgn,uint8_t *buf){
    int32_t ret = 0;
    if(gunnum <= GUN_NUM) {
        ret = get_canrecv(&Mgr, gunnum, pgn, buf);
    }
    return ret;
}

void can_module_clear_ack(uint32_t gunnum, uint32_t pgn){
    clear_canrecv(&Mgr, gunnum, pgn);
}

